/*
 * AndTest.h
 *
 * Created on : 24-05-2014
 *     Author : A.W. Janisse
 *
 * Version 1.0: 24-05-2014, Final release
 */

#include "gtest/gtest.h"

#include "High.h"
#include "And.h"

/**
 * Deze test toon aan dat er het object aangemaakt en opgeruimd (delete) kan
 * worden.
 *
 * De test case is geslaag als de instantie van and niet NULL is en er geen runtime
 * error komen.
 */
TEST(AND, ConstructorDestructorTest)
{
    And *andGate = new And(0,0,"And");
    ASSERT_TRUE(andGate != NULL);
    delete andGate;
}

/**
 * Deze test toont aan dat de gate intern de juiste X en Y positie heeft.
 *
 * De test is geslaagd als de opgevraagde X en Y correct zijn
 */
TEST(AND, GetXYWorksOK)
{
    And *andGate  = new And(20,10,"And");

    EXPECT_EQ(20, andGate->getX());
    EXPECT_EQ(10, andGate->getY());

    delete andGate;
}

/**
 * Deze test toont aan dat het het type juist is.
 *
 * De test is geslaagd als het opgevraagde type correct is.
 */
 TEST(AND, TypeIsJuist)
 {
    And *andGate  = new And(20,10,"And");

    EXPECT_EQ("And", andGate->getType());

    delete andGate;
 }

/**
 * Deze test toont aan dat een entry gate opgevraagd kan worden.
 *
 * De test is gelsaagd als:
 *   1. Er een NULL komt als er geen entries zijn.
 *   2. De juiste entry 1 opgevraagd kan worden.
 *   3. De juiste entry 2 opgevraagd kan worden.
 */
 TEST(AND, GetEntryWorksOk)
 {
    And *andGate  = new And(20,10,"And");
    andGate->resetNextNumber();

    EXPECT_EQ(NULL, andGate->getEntry(0));
    EXPECT_EQ(NULL, andGate->getEntry(1));

    And *g1 = new And(0,0,"And");
    And *g2 = new And(0,10,"And");

    andGate->connectEntryTo(g1);
    andGate->connectEntryTo(g2);

    EXPECT_EQ(1, andGate->getEntry(0)->getNumber());
    EXPECT_EQ(2, andGate->getEntry(1)->getNumber());

    delete andGate;
    delete g1;
    delete g2;
 }

/**
 * deze testcase toont aan dat entries gewist kunnen worden. Hiervoor aan een AND gate twee
 * entries toegevoed waarna deze een voor een gewist worden.
 *
 * De test is geslaagd als:
 *   1. Entry 1 eenmaal gewist kan worden.
 *   2. Entry 2 eenmaal gewist kan worden.
 */
TEST(AND, RemoveEntryWorksOk)
{
    And *andGate  = new And(20,10,"And");
    andGate->resetNextNumber();

    EXPECT_EQ(NULL, andGate->getEntry(0));
    EXPECT_EQ(NULL, andGate->getEntry(1));

    And *g1 = new And(0,0,"And");
    And *g2 = new And(0,10,"And");

    andGate->connectEntryTo(g1);
    andGate->connectEntryTo(g2);

    EXPECT_EQ(true,  andGate->removeEntryTo(g1));
    EXPECT_EQ(false, andGate->removeEntryTo(g1));
    EXPECT_EQ(true,  andGate->removeEntryTo(g2));
    EXPECT_EQ(false, andGate->removeEntryTo(g2));

    delete andGate;
    delete g1;
    delete g2;
}

/**
 * Deze test toont aan dat de logische AND functie het juiste reslutaat geeft.
 *
 * De test is gelaagd als:
 *   1. Twee low inputs een low output geven.
 *   2. Een low en een high input een low output geven.
 *   3. Twee high inputs een high output geven.
 */
TEST(AND, GetOutputValueWorksOK)
{
    High *high1 = new High(10, 20, "High");
    High *high2 = new High(10, 30, "High");
    And *andGate = new And(40,40, "And");

    EXPECT_EQ(false, andGate->getOutputValue());
    andGate->connectEntryTo(high1);
    EXPECT_EQ(false, andGate->getOutputValue());
    andGate->connectEntryTo(high2);
    EXPECT_EQ(true, andGate->getOutputValue());

    delete high1;
    delete high2;
    delete andGate;
}

/**
 * Deze test controleert of de AND gate de juiste drawing instruction levert. De drawing instruction is
 * een string waarin informatie staat over de gate zelf maar ook over de connections. In de opbouw
 * van de string wordt rekening gehouden met de logische toestand van de gate.
 *
 * De test is geslaagd als de juiste strings terug gegeven worden.
 */
TEST(AND, GetDrawingInstructions)
{
    High *h1 = new High(0,0,"High");
    High *h2 = new High(0,20,"High");
    h1->resetNextNumber();

    Gate * g1 = new And(10, 15, "And");
    EXPECT_EQ("gate,1,And,10,15,2,L,L,L\n", g1->getDrawingInstruction());

    Gate * g2 = new And(40, 50, "And");
    EXPECT_EQ("gate,2,And,40,50,2,L,L,L\n", g2->getDrawingInstruction());

    g1->connectEntryTo(h1);
    EXPECT_EQ("connection,H,8,3,10,17\ngate,1,And,10,15,2,H,L,L\n", g1->getDrawingInstruction());

    g1->connectEntryTo(h2);
    EXPECT_EQ("connection,H,8,3,10,17\nconnection,H,8,23,10,19\ngate,1,And,10,15,2,H,H,H\n", g1->getDrawingInstruction());

    delete h1;
    delete g1;
    delete g2;
}
